package com.breeze.components.socket.redis;

import com.breeze.components.socket.WebSocketManager;
import com.breeze.components.socket.WebSocketProperties;
import com.breeze.components.socket.redis.action.ActionConfig;
import lombok.Getter;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

/**
 * redis 集群 websocket配置
 *
 * @author breeze
 */
@Getter
@ConditionalOnProperty(prefix = "breeze.websocket", name = "isCluster", havingValue = "true")
@AutoConfiguration
@EnableConfigurationProperties(WebSocketProperties.class)
@Import(ActionConfig.class)
public class RedisWebSocketConfig implements ApplicationContextAware {

  private ApplicationContext applicationContext;

  @Override
  public void setApplicationContext(@NonNull ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
  }

  @Bean(WebSocketManager.WEBSOCKET_MANAGER_NAME)
  @ConditionalOnMissingBean(name = WebSocketManager.WEBSOCKET_MANAGER_NAME)
  public RedisWebSocketManager webSocketManager(
      @Autowired StringRedisTemplate stringRedisTemplate) {
    return new RedisWebSocketManager(stringRedisTemplate);
  }

  @Bean(RedisReceiver.REDIS_RECEIVER_NAME)
  public RedisReceiver redisReceiver() {
    return new DefaultRedisReceiver(getApplicationContext());
  }

  @Bean("websocketListenerAdapter")
  @Primary
  public MessageListenerAdapter websocketListenerAdapter(
      @Qualifier(RedisReceiver.REDIS_RECEIVER_NAME) RedisReceiver redisReceiver) {
    return new MessageListenerAdapter(redisReceiver, RedisReceiver.RECEIVER_METHOD_NAME);
  }

  @Bean("redisMessageListenerContainer")
  public RedisMessageListenerContainer redisMessageListenerContainer(
      RedisConnectionFactory connectionFactory, MessageListenerAdapter websocketListenerAdapter) {
    RedisMessageListenerContainer container = new RedisMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    container.addMessageListener(
        websocketListenerAdapter, new PatternTopic(RedisWebSocketManager.CHANNEL));
    return container;
  }
}
